package service

import (
	"context"

	"gitee.com/zhaokangming/tiny-ticktok/pkg/errcode"
	"gitee.com/zhaokangming/tiny-ticktok/pkg/util/auth"
	"golang.org/x/crypto/bcrypt"

	"gitee.com/zhaokangming/tiny-ticktok/dao"
	"gitee.com/zhaokangming/tiny-ticktok/model"
)

// IsUserExist 判断用户名是否存在
func IsUserExist(ctx context.Context, username string) (bool, error) {
	user, err := dao.GetUserByName(ctx, username)
	if err != nil {
		return false, err
	}

	return user.ID > 0, nil
}

func QueryFollowInfo(ctx context.Context, user *model.User, curID, targetID int64) {
	user.FollowCount = dao.QueryFollowCount(ctx, targetID)
	user.FollowerCount = dao.QueryFollowerCount(ctx, targetID)
	user.IsFollow = dao.QueryIsFollow(ctx, curID, targetID)
}

// QueryUser 查询目标用户的信息，curId传进来只是为了判断目标用户与当前用户的关系(isFollow)
func QueryUser(ctx context.Context, curID, targetID int64) (*model.User, error) {
	user, err := dao.QueryUser(ctx, targetID)
	if err != nil {
		return nil, err
	}

	res := model.User{Id: int64(user.ID), Name: user.Name}
	QueryFollowInfo(ctx, &res, curID, targetID)
	return &res, nil
}

// Login 登录流程
func Login(ctx context.Context, name string, password string) (*model.UserLoginResponse, error) {
	if len(name) == 0 || len(password) == 0 {
		return nil, errcode.ErrLoginFail
	}

	user, err := dao.GetUserByName(ctx, name)
	if err != nil {
		return nil, errcode.ErrLoginFail
	}

	if user.ID == 0 {
		return nil, errcode.ErrLoginFail
	}

	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		return nil, errcode.ErrLoginFail
	}

	token, err := auth.CreateToken(int64(user.ID))
	if err != nil {
		return nil, err
	}

	return &model.UserLoginResponse{UserId: int64(user.ID), Token: token}, nil
}

// Register 注册流程
func Register(ctx context.Context, name string, password string) (*model.UserLoginResponse, error) {
	// 如果用户名或密码为空,或者用户名密码有一者大于32字符
	if len(name) == 0 || len(password) == 0 {
		return nil, errcode.ErrParamTypeError
	} else if len(name) > 32 || len(password) > 32 {
		return nil, errcode.ErrParamTypeError
	}

	// 判断用户是否存在
	ok, err := IsUserExist(ctx, name)
	// 操作数据库的过程会不会有err
	if err != nil {
		return nil, err
	}
	// 存在相同的用户返回
	if ok {
		return nil, errcode.ErrUsernameHadBeenRegistered
	}

	// 通过bcrypt加密密码
	hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}
	password = string(hash)

	// 数据库数据创建失败的情况
	id, err := dao.CreateUser(ctx, dao.User{Name: name, Password: password})
	if err != nil {
		return nil, err
	}

	// 创建token失败的情况
	token, err := auth.CreateToken(id)
	if err != nil {
		return nil, errcode.ErrLoginFail
	}

	return &model.UserLoginResponse{UserId: id, Token: token}, nil
}
